﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Windows.Media;
using Elca.MvvmHelpers;

namespace ULSDeobfuscator {

    public class ManageColorRulesViewModel : BaseViewModel {

        public ICommand OKCommand { get; private set; }
        public ICommand CancelCommand { get; private set; }
        public ICommand AddCommand { get; private set; }
        public ICommand EditCommand { get; private set; }
        public ICommand DeleteCommand { get; private set; }
        public ICommand MoveRuleUpCommand { get; private set; }
        public ICommand MoveRuleDownCommand { get; private set; }


        private ColorRuleViewModel _currentRule;

        public ColorRuleViewModel CurrentRule {
            get { return _currentRule; }
            set {
                if (_currentRule != value) {
                    _currentRule = value;
                    OnPropertyChanged("CurrentRule");
                }
            }
        }

        private int _currentRuleIndex;
        public int CurrentRuleIndex {
            get { return _currentRuleIndex; }
            set {
                if (_currentRuleIndex != value) {
                    _currentRuleIndex = value;
                    OnPropertyChanged("CurrentRuleIndex");
                }
            }
        }

        public ObservableCollection<ColorRuleViewModel> Rules { get; private set; }

        private readonly List<FilterChoice> _processesList = new List<FilterChoice>();
        private readonly List<FilterChoice> _areasList = new List<FilterChoice>();
        private readonly List<FilterChoice> _categoriesList = new List<FilterChoice>();
        private readonly List<FilterChoice> _levelsList = new List<FilterChoice>();
        private readonly List<FilterChoice> _eventIDsList = new List<FilterChoice>();

        public double WindowHeight {
            get { return App.GlobalSettings.ManageColorRulesWindowHeight; }
            set {
                if (App.GlobalSettings.ManageColorRulesWindowHeight != value) {
                    App.GlobalSettings.ManageColorRulesWindowHeight = value;
                    OnPropertyChanged("WindowHeight");
                }
            }
        }

        public double WindowWidth {
            get { return App.GlobalSettings.ManageColorRulesWindowWidth; }
            set {
                if (App.GlobalSettings.ManageColorRulesWindowWidth != value) {
                    App.GlobalSettings.ManageColorRulesWindowWidth = value;
                    OnPropertyChanged("WindowWidth");
                }
            }
        }

        public double WindowLeft {
            get { return App.GlobalSettings.ManageColorRulesWindowLeft; }
            set {
                if (App.GlobalSettings.ManageColorRulesWindowLeft != value) {
                    App.GlobalSettings.ManageColorRulesWindowLeft = value;
                    OnPropertyChanged("WindowLeft");
                }
            }
        }

        public double WindowTop {
            get { return App.GlobalSettings.ManageColorRulesWindowTop; }
            set {
                if (App.GlobalSettings.ManageColorRulesWindowTop != value) {
                    App.GlobalSettings.ManageColorRulesWindowTop = value;
                    OnPropertyChanged("WindowTop");
                }
            }
        }

        public double NameColumnWidth {
            get { return App.GlobalSettings.ManageColorRulesNameWidth; }
            set {
                if (App.GlobalSettings.ManageColorRulesNameWidth != value) {
                    App.GlobalSettings.ManageColorRulesNameWidth = value;
                    OnPropertyChanged("NameColumnWidth");
                }
            }
        }

        public double ColorColumnWidth {
            get { return App.GlobalSettings.ManageColorRulesColorWidth; }
            set {
                if (App.GlobalSettings.ManageColorRulesColorWidth != value) {
                    App.GlobalSettings.ManageColorRulesColorWidth = value;
                    OnPropertyChanged("ColorColumnWidth");
                }
            }
        }

        public double ProcessColumnWidth {
            get { return App.GlobalSettings.ManageColorRulesProcessWidth; }
            set {
                if (App.GlobalSettings.ManageColorRulesProcessWidth != value) {
                    App.GlobalSettings.ManageColorRulesProcessWidth = value;
                    OnPropertyChanged("ProcessColumnWidth");
                }
            }
        }

        public double AreaColumnWidth {
            get { return App.GlobalSettings.ManageColorRulesAreaWidth; }
            set {
                if (App.GlobalSettings.ManageColorRulesAreaWidth != value) {
                    App.GlobalSettings.ManageColorRulesAreaWidth = value;
                    OnPropertyChanged("AreaColumnWidth");
                }
            }
        }

        public double CategoryColumnWidth {
            get { return App.GlobalSettings.ManageColorRulesCategoryWidth; }
            set {
                if (App.GlobalSettings.ManageColorRulesCategoryWidth != value) {
                    App.GlobalSettings.ManageColorRulesCategoryWidth = value;
                    OnPropertyChanged("CategoryColumnWidth");
                }
            }
        }

        public double LevelColumnWidth {
            get { return App.GlobalSettings.ManageColorRulesLevelWidth; }
            set {
                if (App.GlobalSettings.ManageColorRulesLevelWidth != value) {
                    App.GlobalSettings.ManageColorRulesLevelWidth = value;
                    OnPropertyChanged("LevelColumnWidth");
                }
            }
        }

        public double EventColumnWidth {
            get { return App.GlobalSettings.ManageColorRulesEventWidth; }
            set {
                if (App.GlobalSettings.ManageColorRulesEventWidth != value) {
                    App.GlobalSettings.ManageColorRulesEventWidth = value;
                    OnPropertyChanged("EventColumnWidth");
                }
            }
        }

        public double MessageColumnWidth {
            get { return App.GlobalSettings.ManageColorRulesMessageWidth; }
            set {
                if (App.GlobalSettings.ManageColorRulesMessageWidth != value) {
                    App.GlobalSettings.ManageColorRulesMessageWidth = value;
                    OnPropertyChanged("MessageColumnWidth");
                }
            }
        }

        public double CorrelationColumnWidth {
            get { return App.GlobalSettings.ManageColorRulesCorrelationWidth; }
            set {
                if (App.GlobalSettings.ManageColorRulesCorrelationWidth != value) {
                    App.GlobalSettings.ManageColorRulesCorrelationWidth = value;
                    OnPropertyChanged("CorrelationColumnWidth");
                }
            }
        }

        public double MultiLineColumnWidth {
            get { return App.GlobalSettings.ManageColorRulesMultiLineWidth; }
            set {
                if (App.GlobalSettings.ManageColorRulesMultiLineWidth != value) {
                    App.GlobalSettings.ManageColorRulesMultiLineWidth = value;
                    OnPropertyChanged("MultiLineColumnWidth");
                }
            }
        }

        public double PersistentColumnWidth {
            get { return App.GlobalSettings.ManageColorRulesPersistentWidth; }
            set {
                if (App.GlobalSettings.ManageColorRulesPersistentWidth != value) {
                    App.GlobalSettings.ManageColorRulesPersistentWidth = value;
                    OnPropertyChanged("PersistentColumnWidth");
                }
            }
        }

        private Color _defaultForegroundColor;
        public Color DefaultForegroundColor {
            get { return _defaultForegroundColor; }
            set {
                if (_defaultForegroundColor != value) {
                    _defaultForegroundColor = value;
                    InformRuleColorChange();
                    OnPropertyChanged("DefaultForegroundColor");
                }
            }
        }

        private Color _defaultBackgroundColor;
        public Color DefaultBackgroundColor {
            get { return _defaultBackgroundColor; }
            set {
                if (_defaultBackgroundColor != value) {
                    _defaultBackgroundColor = value;
                    InformRuleColorChange();
                    OnPropertyChanged("DefaultBackgroundColor");
                }
            }
        }

        private Color _highlightForegroundColor;
        public Color HighlightForegroundColor {
            get { return _highlightForegroundColor; }
            set {
                if (_highlightForegroundColor != value) {
                    _highlightForegroundColor = value;
                    OnPropertyChanged("HighlightForegroundColor");
                }
            }
        }

        private Color _highlightBackgroundColor;
        public Color HighlightBackgroundColor {
            get { return _highlightBackgroundColor; }
            set {
                if (_highlightBackgroundColor != value) {
                    _highlightBackgroundColor = value;
                    OnPropertyChanged("HighlightBackgroundColor");
                }
            }
        }

        public ManageColorRulesViewModel(IEnumerable<ColorRule> initialRules) {
            
            OKCommand = new ExecutableCommand(OnOK);
            CancelCommand = new ExecutableCommand(OnCancel);
            AddCommand = new ExecutableCommand(OnAddRule);
            EditCommand = new ConditionalCommand(OnEditRule, () => _currentRule != null);
            DeleteCommand = new ConditionalCommand(OnDeleteFilter, () => _currentRule != null);
            MoveRuleUpCommand = new ConditionalCommand(OnMoveUpRule, () => _currentRule != null && CurrentRuleIndex > 0);
            MoveRuleDownCommand = new ConditionalCommand(OnMoveDownRule, () => _currentRule != null && CurrentRuleIndex < Rules.Count - 1);

            Rules = new ObservableCollection<ColorRuleViewModel>(
                initialRules.Select(
                    r => new ColorRuleViewModel { 
                        Rule = r,
                        Parent = this,
                }));
        }

        private void OnClosing() {
            
        }

        private void OnOK() {
            OnClosing();
            RaiseCloseRequest(true);
        }

        private void OnCancel() {
            OnClosing();
            RaiseCloseRequest(false);
        }

        private void OnDeleteFilter() {

            Rules.Remove(CurrentRule);
        }

        private void OnMoveUpRule() {
            
            Rules.Move(CurrentRuleIndex, CurrentRuleIndex -1);
        }

        private void OnMoveDownRule() {
            Rules.Move(CurrentRuleIndex, CurrentRuleIndex + 1);
        }

        public void SetProcessesList(IEnumerable<FilterChoice> processesList ) {
         
            _processesList.Clear();
            _processesList.AddRange(processesList.Select(fc => new FilterChoice {
                    ItemName = fc.ItemName
            }));
            _processesList.Add(new FilterChoice {
                    ItemName = ColorRule.AnyWorkerProcess
            });
        }

        public void SetAreasList(IEnumerable<FilterChoice> areasList) {
            _areasList.Clear();
            _areasList.AddRange(areasList.Select(fc => new FilterChoice {
                    ItemName = fc.ItemName
            }));
        }

        public void SetCategoriesList(IEnumerable<FilterChoice> categoriesList) {
            _categoriesList.Clear();
            _categoriesList.AddRange(categoriesList.Select(fc => new FilterChoice {
                ItemName = fc.ItemName
            }));
        }

        public void SetLevelsList(IEnumerable<FilterChoice> levelsList) {
            _levelsList.Clear();
            _levelsList.AddRange(levelsList.Select(fc => new FilterChoice {
                    ItemName = fc.ItemName
            }));
        }

        public void SetEventIDsList(IEnumerable<FilterChoice> eventIDsList) {
            _eventIDsList.Clear();
            _eventIDsList.AddRange(eventIDsList.Select(fc => new FilterChoice {
                    ItemName = fc.ItemName
            }));
        }

        private void OnAddRule() {

            ColorRule cr = new ColorRule();
            EditColorRuleViewModel ecrvm = CreateEditColorRuleViewModel(cr);
            ecrvm.Title = "Create new color rule";

            IUIVisualizer viz = ServiceRegistry.Resolve<IUIVisualizer>();
        
            if (viz.ShowDialog(App.EditColorRule, ecrvm) == true) {

                ColorRuleViewModel crvm = new ColorRuleViewModel { Rule=cr, Parent = this };
                Rules.Add(crvm);
                CurrentRule = crvm;
            }
        }

        private void OnEditRule() {

            ColorRule tempRule = CurrentRule.Rule.Clone();

            EditColorRuleViewModel ecrvm = CreateEditColorRuleViewModel(tempRule);
            ecrvm.Title = "Edit the color rule";

            IUIVisualizer viz = ServiceRegistry.Resolve<IUIVisualizer>();

            if (viz.ShowDialog(App.EditColorRule, ecrvm) == true) {

                tempRule.CopyTo(CurrentRule.Rule);
                CurrentRule.RefreshUI();
            }
        }

        private EditColorRuleViewModel CreateEditColorRuleViewModel(ColorRule cr) {
            
            EditColorRuleViewModel ecrvm = new EditColorRuleViewModel();
            // the rule must be set before the elements before
            ecrvm.Rule = cr;
            ecrvm.SetProcessesList(_processesList);
            ecrvm.SetAreasList(_areasList);
            ecrvm.SetCategoriesList(_categoriesList);
            ecrvm.SetLevelsList(_levelsList);
            ecrvm.SetEventIDsList(_eventIDsList);
            ecrvm.DefaultForegroundColor = DefaultForegroundColor;
            ecrvm.DefaultBackgroundColor = DefaultBackgroundColor;

            return ecrvm;
        }

        private void InformRuleColorChange() {
         
            foreach (ColorRuleViewModel crvm in Rules) {
                crvm.InformColorChange();
            }
        }
    }

    public class ColorRuleViewModel : BaseNotifyableObject {

        public ColorRule Rule { get; set; }
        public ManageColorRulesViewModel Parent { get; set; }

        public string ProcessSummary {
            get { return String.Join(", ", Rule.Processes.ToArray()); }
        }
        public string AreaSummary {
            get { return String.Join(", ", Rule.Areas.ToArray()); }
        }
        public string CategorySummary {
            get { return String.Join(", ", Rule.Categories.ToArray()); }
        }
        public string LevelSummary {
            get { return String.Join(", ", Rule.Levels.ToArray()); }
        }
        public string EventIDSummary {
            get { return String.Join(", ", Rule.EventIDs.ToArray()); }
        }

        public Color ForegroundColor {
            get { return Rule.ForegroundColor ?? Parent.DefaultForegroundColor; }
        }
        public Color BackgroundColor {
            get { return Rule.BackgroundColor ?? Parent.DefaultBackgroundColor; }
        }

        public void RefreshUI() {
            OnPropertyChanged("ProcessSummary");
            OnPropertyChanged("AreaSummary");
            OnPropertyChanged("CategorySummary");
            OnPropertyChanged("LevelSummary");
            OnPropertyChanged("EventIDSummary");
            InformColorChange();
        }

        public void InformColorChange() {
            OnPropertyChanged("ForegroundColor");
            OnPropertyChanged("BackgroundColor");
        }
    }
}
